package javango.contrib.admin.util;

import javango.contrib.hibernate.Pagination;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class Paginator {

	private static Log log = LogFactory.getLog(Paginator.class);

	public final static String TEXT_NEXT = "Next";
	public final static String TEXT_FIRST = "First";
	public final static String TEXT_PREV = "Prev";
	public final static String TEXT_LAST = "Last";

	public final static String TEXT_NORESULTS = "No Results";
	public final static String TEXT_NBSP = "&nbsp;";
	public final static String TEXT_SHOWING = "Showing";

	private String query_string;
	
	private Pagination pagination;
	
	public Paginator(Pagination p) {
		this.pagination = p;
	}
	public Paginator(Pagination p, String query_string) {
		this.pagination = p;
		this.query_string = query_string;
	}
	
	public String asTable() {
		StringBuilder out = new StringBuilder();

		out.append("<table width='90%'>\n<tr>");
		displayFirst(out, pagination);
		displayPrev(out, pagination);
		displayDescription(out, pagination);
		displayNext(out, pagination);
		displayLast(out, pagination);
		out.append("</tr>\n</table>\n");

		return out.toString();
	}


	/**
	 * displays the
	 * <td> with the correct link and description. If both params are null the
	 * description will not be hyper linked.
	 * 
	 * @param desc
	 * @param page
	 *            Integer The first row (null to keep the current first row)
	 * @param max
	 *            Integer The max number of rows per page (null to keep the
	 *            current value)
	 */
	private void showLink(StringBuilder out, String desc, Long page) {
		out.append("<td align='center'>");
		if (page != null) {
			out.append(String.format("<a href=\"./?p=%d&%s\">", page, query_string == null ? "" : query_string));
			out.append(desc);
			out.append("</a>");
		} else {
			out.append(desc);
		}
		out.append("</td>");
	}

	private void displayFirst(StringBuilder out, Pagination pagination) {
		if (pagination.getHits().intValue() == 0) {
			showLink(out, TEXT_FIRST, null);
		} else {
			showLink(out, TEXT_FIRST, new Long(1));
		}
			
	}

	private void displayPrev(StringBuilder out, Pagination pagination) {
		if (!pagination.isHas_previous()) {
			showLink(out, TEXT_PREV, null);
		} else {
			showLink(out, TEXT_PREV, pagination.getPrevious());
		}
	}

	private void displayNext(StringBuilder out, Pagination pagination) {
		if (!pagination.isHas_next()) {
			showLink(out, TEXT_NEXT, null);
		} else {
			showLink(out, TEXT_NEXT, pagination.getNext());
		}
	}

	private void displayLast(StringBuilder out, Pagination pagination) {
		if (pagination.getHits().intValue() == 0) {
			showLink(out, TEXT_LAST, null);
		} else {
			showLink(out, TEXT_LAST, pagination.getPages());
		}
	}

	private void displayDescription(StringBuilder out, Pagination pagination) {
		Long first = pagination.getFirst_on_page();
		Long max = pagination.getPaginate_by(); 
		Long total = pagination.getHits();
		
		out.append("<td width='75%' align='center'>");
		if (total.intValue() == 0) {
			out.append(TEXT_NORESULTS);
		} else if (first == null && max == null && total == null) {
			out.append(TEXT_NBSP);
		} else if (first != null && max != null && total != null) {
			int end = first.intValue() + max.intValue() - 1;
			// -1 because we are 1 based.
			if (end > total.intValue())
				end = total.intValue();
			out.append(TEXT_SHOWING + " " + first + " - " + end + " of "
					+ total);
		} else if (first != null && total != null) {
			out.append(TEXT_SHOWING + " " + first.intValue() + " - "
					+ total.intValue() + " of " + total.intValue());
		} else {
			out.append("&nbsp;");
		}

		out.append("</td>");
	}

	public String getQuery_string() {
		return query_string;
	}

	public void setQuery_string(String query_string) {
		this.query_string = query_string;
	}
}
